package com.xbongbong.parent.abstracts;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormSubDataEntity;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.dto.DeleteDTO;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.PhysicalDeleteDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.parent.interfaces.FormDataService;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.formdata.pojo.SaveFormExplainPojo;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.saas.model.IndexTypeModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2022/01/06 14:45
 */
@Component
public abstract class AbstractParentAddFormDataService<F, D> implements FormDataService<F, D> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractParentUpdateFormDataService.class);

    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Override
    public FormDataAddVO addAndImport(FormDataAddDTO formDataAddDTO) throws XbbException {
        if (Objects.equals(formDataAddDTO.getIsImport(), 1)) {
            LOGGER.info("com.xbongbong.paas.service.impl.MarketActivityFormDataServiceImpl.save = " + formDataAddDTO.getCorpid() + ">>>" + formDataAddDTO.getIsImport());
            return importData(formDataAddDTO);
        } else {
            return add(formDataAddDTO);
        }
    }

    @Override
    public FormDataAddVO add(  FormDataAddDTO formDataAddDTO) throws XbbException {
        Long formId = formDataAddDTO.getFormId();
        String corpid = formDataAddDTO.getCorpid();
        // 1.获取表单实体
        F paasFormEntityExt = getFormEntity(formDataAddDTO);
        // 2.获取表单解释
        SaveFormExplainPojo saveFormExplainDTO = getExplainMap(formId, corpid);
        ///3.根据表单获取是否开启流程，然后拿到流程起始节点的可见字段
        Map<String, FieldAttrEntity> explainMap = processSetVisible(paasFormEntityExt, formDataAddDTO, saveFormExplainDTO.getExplainMap());

        JSONObject data = formDataAddDTO.getDataList();
        ValidateDataDTO validateDataDTO = new ValidateDataDTO();
        BeanUtil.copyProperties(formDataAddDTO, validateDataDTO);
        validateDataDTO.setFromApproval(formDataAddDTO.getFromApproval());
        validateDataDTO.setData(data);
        validateDataDTO.setExplainMap(explainMap);
        validateDataDTO.setOwnerIds(formDataAddDTO.getOwnerId());
        ///4.解析数据，校验必填字段，校验各个业务的逻辑
        analyticalData(formDataAddDTO, validateDataDTO, explainMap);
        ///5.拼装数据实体
        D paasFormDataEntity = getFormData(formDataAddDTO, paasFormEntityExt, explainMap, validateDataDTO.getDepartmentId(), validateDataDTO.getData());
        // 6. 开始工作流或者流程审批
        BeforeSaveVO beforeSaveVO = startWorkflowOrProcess(paasFormDataEntity, paasFormEntityExt, validateDataDTO.getSaasNeedRedundantAttrPoJo(), formDataAddDTO, explainMap, saveFormExplainDTO.getExplainList());
        // 保存逻辑和保存之后的逻辑
        return addNoValidate(beforeSaveVO, formDataAddDTO, paasFormEntityExt, paasFormDataEntity);
    }


    @Override
    public FormDataAddVO importData( FormDataAddDTO formDataAddDTO) throws XbbException {
        Long formId = formDataAddDTO.getFormId();
        String corpid = formDataAddDTO.getCorpid();
        // 1.获取表单实体
        F paasFormEntityExt = getFormEntity(formDataAddDTO);
        // 2.获取表单解释
        SaveFormExplainPojo saveFormExplainDTO = getExplainMap(formId, corpid);
        // 3.根据com.xbongbong.paas.pojo.dto.FormDataAddDTO.attrList，返回部分导入字段，如果com.xbongbong.paas.pojo.dto.FormDataAddDTO.attrList为空，则按照正常返回
        Map<String, FieldAttrEntity> explainMap = importProcessSetVisible(paasFormEntityExt, formDataAddDTO, saveFormExplainDTO.getExplainMap());

        JSONObject data = formDataAddDTO.getDataList();
        ValidateDataDTO validateDataDTO = new ValidateDataDTO();
        BeanUtil.copyProperties(formDataAddDTO, validateDataDTO);
        validateDataDTO.setExplainMap(explainMap);
        validateDataDTO.setData(data);
        validateDataDTO.setOwnerIds(formDataAddDTO.getOwnerId());
        // 4.解析数据、校验必填字段、校验各个业务的逻辑
        analyticalData(formDataAddDTO, validateDataDTO, explainMap);
        // 5.拼装数据实体
        D paasFormDataEntity = getFormData(formDataAddDTO, paasFormEntityExt, explainMap, validateDataDTO.getDepartmentId(), validateDataDTO.getData());
        // 6. 开始工作流
        BeforeSaveVO beforeSaveVO = startWorkFlow(paasFormDataEntity, paasFormEntityExt, validateDataDTO.getSaasNeedRedundantAttrPoJo(), formDataAddDTO, explainMap, saveFormExplainDTO.getExplainList());
        // 保存逻辑和保存之后的逻辑
        return addNoValidate(beforeSaveVO, formDataAddDTO, paasFormEntityExt, paasFormDataEntity);
    }

    @Override
    public FormDataAddVO addNoValidate(BeforeSaveVO beforeSaveVO, FormDataAddDTO formDataAddDTO, F paasFormEntityExt , D formData) throws XbbException {
        FormDataAddVO formDataSaveVO;
        //是否触发工作流
        formDataAddDTO.setExplainMap(beforeSaveVO.getExplainMap());
        if (formDataAddDTO.getIsSatisfyTrigger()) {
            String pojo = JSON.toJSONString(beforeSaveVO.getSaasNeedRedundantAttrPojo(), SerializerFeature.DisableCircularReferenceDetect);
            SaasNeedRedundantAttrPojo needRedundantAttrPojo = JSON.parseObject(pojo, SaasNeedRedundantAttrPojo.class);
            // 保存数据
            SaveVO saveVO = saveForWorkflow(formDataAddDTO, beforeSaveVO, paasFormEntityExt, formData);
            // 保存之后的逻辑，区分于afterSave，有部分逻辑，需要在走完审批在com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy.save中执行
            formDataSaveVO = afterSaveForWorkflow(formDataAddDTO, beforeSaveVO, saveVO, paasFormEntityExt, formData);
            formDataSaveVO.setFormDataId(saveVO.getDataId());
            beforeSaveVO.setSaasNeedRedundantAttrPojo(needRedundantAttrPojo);
            // 发送工作流消息至工作流消费者
            workflowAddTrigger(formDataAddDTO, beforeSaveVO, formDataSaveVO);
        } else {
            // 保存数据、文件柜
            SaveVO saveVO = save(formDataAddDTO, beforeSaveVO, paasFormEntityExt, formData);
            // 保存之后的逻辑，如客户：保存客户联系人，客户团队，执行apiHook，低代码，业务规则
            formDataSaveVO = afterSave(formDataAddDTO, beforeSaveVO, saveVO, paasFormEntityExt, formData);
            formDataSaveVO.setFormDataId(saveVO.getDataId());
        }
        return formDataSaveVO;
    }

    /**
     * Description:
     * @param saasMark
     * @param businessType
     * @return com.xbongbong.paas.enums.IndexTypeEnum
     * @throws
     * @author 魏荣杰
     * @date 2020/12/31 17:13
     * @since
     */
    protected IndexTypeEnum getIndexTypeEnum(String corpid, Integer saasMark, Integer businessType) throws XbbException {
        return indexTypeModel.getIndexType(corpid, businessType, saasMark);
    }

    /**
     * Description: 主业务数据物理删除
     * @param dataId 数据id
     * @param corpid 公司id
     * @param indexTypeEnum es索引枚举
     * @see IndexTypeEnum
     * @author 魏荣杰
     * @date 2020/12/31 17:10
     */
    protected void physicalDeleteFormData(Long dataId, String corpid, IndexTypeEnum indexTypeEnum) throws XbbException {
        PhysicalDeleteDTO physicalDeleteDTO = new PhysicalDeleteDTO();
        physicalDeleteDTO.setEsId(corpid + "_" + dataId);
        physicalDeleteDTO.setIndex(indexTypeEnum.getIndex());
        physicalDeleteDTO.setType(indexTypeEnum.getType());
        paasEsModel.physicalDelete(physicalDeleteDTO);
    }

    /**
     * Description: 物理删除子表单数据
     * @param corpid
     * @param subDataEntities
     * @param indexTypeEnum
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2020/9/30 15:35
     * @since
     */
    protected void physicalDeleteSubBatch(String corpid, List<? extends PaasFormSubDataEntity> subDataEntities, IndexTypeEnum indexTypeEnum) throws XbbException {
        List<DeleteDTO> deleteSubList = new ArrayList<>();
        for (PaasFormSubDataEntity paasFormSubDataEntity : subDataEntities) {
            DeleteDTO deleteDTO = new DeleteDTO();
            deleteDTO.setEsId(corpid + "_" + paasFormSubDataEntity.getId());
            deleteDTO.setIndexTypeEnum(indexTypeEnum);
            deleteDTO.setParent(corpid + "_" + paasFormSubDataEntity.getDataId());
            deleteSubList.add(deleteDTO);
        }
        paasEsModel.physicalDeleteBatchChild(deleteSubList, corpid, indexTypeEnum);
    }

    /**
     * 设置部分属性，用于返回
     * @param dataId 数据id
     * @param subFormData 子表单数据封装
     * @param data 主表数据
     * @param addTime 创建时间
     * @param updateTime 更新时间
     * @param paasFormDataEntity 数据实体
     * @param beforeSaveVO
     * @return void
     * @author 吴峰
     * @date 2021/2/3 15:14
     * @throws XbbException
     */
    protected void setPartialAttributes(Long dataId, JSONObject subFormData, JSONObject data, Long addTime, Long updateTime, PaasFormDataEntity paasFormDataEntity, BeforeSaveVO beforeSaveVO) {
        paasFormDataEntity.setId(dataId);
        paasFormDataEntity.setSubFormData(subFormData);
        paasFormDataEntity.setData(data);
        paasFormDataEntity.setAddTime(addTime);
        paasFormDataEntity.setUpdateTime(updateTime);
        beforeSaveVO.setPaasFormDataEntity(paasFormDataEntity);
    }
}
